
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
/** @author  John Miller
 *  @version 1.1
 *  @date    Fri Dec 27 15:41:58 EST 2013
 *  @see     LICENSE (MIT style license file).
 */

package apps.tableau

import scalation.model.TimeUnits._
import scalation.random.{Exponential, Variate}
import scalation.tableau.Model

//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
/** The `CallCenter` class defines a simple tableau model of a Call Center where
 *  service is provided by one tele-service representative and models an M/M/1/1
 *  queue (i.e., no call waiting).
 */
object CallCenter extends App
{
    val stream     = 1                                      // random number stream to use (0 to 99)
    val lambda     = 6.0                                    // customer arrival rate (per hour)
    val mu         = 7.5                                    // customer service rate (per hour)
    val maxCusts   = 10                                     // stopping rule: simulate maxCustss customers
    val iArrivalRV = Exponential (HOUR/lambda, stream)      // inter-arrival time random variate
    val serviceRV  = Exponential (HOUR/mu, stream)          // service time random variate
    val label      = Array ("ID-0", "IArrival-1", "Arrival-2", "Start-3", "Service-4", "End-5", "Wait-6", "Total-7")
    val mm11 = new CallCenterModel ("M/M/1/1 Queue", maxCusts, Array (iArrivalRV, serviceRV), label)
    mm11.simulate ()
    mm11.report

} // CallCenter


//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
/** The `CallModel` class customizes `scalation.tableau.Model` for Call Center
 *  simualtions.
 *  @param name   the name of simulation model
 *  @param m      the number entities to process before stopping
 *  @param rv     the random variate generators to use
 *  @param label  the column labels for the matrix
 */
class CallCenterModel (name: String, m: Int, rv: Array [Variate], label: Array [String])
      extends Model (name, m, rv, label)
{
    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    /** Perform tableau-based simulation by recording timing information about
     *  the ith entity in the ith row of the matrix.
     */
    override def simulate ()
    {
        var l = 0                                                 // last established call
        for (i <- 1 to m) {
            table(i, 1) = if (i == 1) 0.0 else rv(0).gen               // IArrival-1
            table(i, 2) = table(i, 1) + table(i-1, 2)                  // Arrival-2
            val serviceT = rv(1).gen
            if (table(l, 5) <= table(i, 2)) {                     // call established
                table(i, 3) = table(i, 2) max table(l, 5)              // Start-3
                l = i
                table(i, 4) = serviceT                                 // Service-4
                table(i, 5) = table(i, 3) + table(i, 4)                // End-5
                table(i, 6) = table(i, 3) - table(i, 2)                // Wait-6
                table(i, 7) = table(i, 5) - table(i, 2)                // Total-7
            } // if
        } // for
    } // simulate

} // CallCenterModel

